<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>打开控制台查看结果</div>
    <button id="btn1">按钮1</button>
    <button id="btn2">按钮2</button>
    <button id="btn3">按钮3</button>
    <hr>
    <button id="switch1">开关1</button>
    <button id="switch2">开关2</button>
    <button id="switch3">开关3</button>
    <script>
        /* 在命令的发布和接收者之间，定义一个命令对象，命令对象暴露出一个统一的接口给命令的发布者，
        而命令的发布者不用去管接收者是如何执行命令的，做到命令发布者和接收者的解耦。*/

        /* 举一个如果页面中有3个按钮，给不同按钮添加不同功能的例子 */
        let btn1 = document.getElementById('btn1')
        let btn2 = document.getElementById('btn2')
        let btn3 = document.getElementById('btn3')

        /** 定义一个命令发布者（执行者）的类 */
        class Executor {
            setCommand(btn,command){
                btn.onclick = function() {
                    command.execute()
                }
            }
        }

        /**
         * 定义一个命令接收者
        */
       class Menu {
        refresh() {
           console.log('刷新菜单');
        }

        addSubMenu() {
            console.log('增加子菜单');
        }
       }

       /**
        * 定义一个刷新菜单的命令对象类
       */
      class RefreshMenu {
        constructor(receiver) {
            // 命令对象与接收者关联
            this.receiver = receiver
        }

        // 暴露出统一的接口给命令发布者Executor
        execute() {
            this.receiver.refresh()
        }
      }

      /**
       * 定义一个增加子菜单的命令对象的类
      */
     class AddSubMenu {
        constructor(receiver) {
            // 命令对象与接收者关联
            this.receiver = receiver
        }
        // 暴露出统一的接口给命令发布者Executor
        execute() {
            this.receiver.addSubMenu()
        }
     }

     let menu = new Menu()  // 命令接收者
     let executor = new Executor()  // 命令发布者
     
     let refreshMenu = new RefreshMenu(menu)  // 刷新菜单的命令对象类

     
     // 命令发布者给按钮1添加刷新功能,参数为btn1节点，刷新菜单的命令类（命令接收者）
     executor.setCommand(btn1,refreshMenu) // 刷新菜单


     let addSubMenu = new AddSubMenu(menu)  
     // 给按钮2添加增加子菜单功能
     executor.setCommand(btn2,addSubMenu)  // 新增菜单

     /* 其实就是通过命令发布者通过命令对象类来调用命令接收者 */


    // 如果想给按钮3增加删除菜单的功能，就继续增加删除菜单的命令对象和接收者的具体删除方法，而不必修改命令对象


    console.log('================练习================');
    (function(){
    let switch1 = document.getElementById('switch1')
    let switch2 = document.getElementById('switch2')
    let switch3 = document.getElementById('switch3')

    /** 定义一个命令发布者的类 */
    class Executor {
        setCommand(btn,command){
            btn.onclick = function() {
                command.execute()
            }
        }
    }

    /** 定义一个接收者 */
    class Menu {
        refresh() {
            console.log('刷新菜单1');
        }

        addSubMenu() {
            console.log('增加菜单1');
        }
    }

    /** 定义一个刷新菜单的命令对象类 */
    class RefreshMenu {
        // 接收指令
        constructor(receiver) {
            this.receiver = receiver
        }

        /** 暴露出统一的接口给命令发布者Executor */
        execute() {
            this.receiver.refresh()  // 执行refresh()方法
        }
    }

    /** 定义一个增加子菜单的命令对象类 */
    class AddSubMenu {
        // 接收指令
        constructor(receiver){
            this.receiver = receiver;
        }

        /** 暴露出统一的接口给命令发布者Executor */
        execute() {
            this.receiver.addSubMenu()  // 执行refresh()方法
        }
    }

    let menu = new Menu(); // 命令接收者
    let executor = new Executor(); // 命令发布者

    let refreshMenu = new RefreshMenu(menu); // 刷新菜单的命令对象类
    // 通过命令发布者发布命令，调用刷新菜单的类
    executor.setCommand(switch1,refreshMenu); // 刷新菜单

    let addSubMenu = new AddSubMenu(menu); // 增加菜单的命令对象类
    // 通过命令发布者发布命令，调用新增菜单的类
    executor.setCommand(switch2,addSubMenu)  // 增加菜单

    })()


    </script>
</body>
</html>